
function init() 
{
    var   b2Vec2 = Box2D.Common.Math.b2Vec2
        , b2AABB = Box2D.Collision.b2AABB
        , b2BodyDef = Box2D.Dynamics.b2BodyDef
        , b2Body = Box2D.Dynamics.b2Body
        , b2FixtureDef = Box2D.Dynamics.b2FixtureDef
        , b2Fixture = Box2D.Dynamics.b2Fixture
        , b2World = Box2D.Dynamics.b2World
        , b2MassData = Box2D.Collision.Shapes.b2MassData
        , b2PolygonShape = Box2D.Collision.Shapes.b2PolygonShape
        , b2CircleShape = Box2D.Collision.Shapes.b2CircleShape
        , b2DebugDraw = Box2D.Dynamics.b2DebugDraw
        , b2MouseJointDef =  Box2D.Dynamics.Joints.b2MouseJointDef
        , b2RevoluteJointDef = Box2D.Dynamics.Joints.b2RevoluteJointDef
        , b2DistanceJointDef = Box2D.Dynamics.Joints.b2DistanceJointDef
        , b2PrismaticJointDef = Box2D.Dynamics.Joints.b2PrismaticJointDef
        , b2PulleyJointDef = Box2D.Dynamics.Joints.b2PulleyJointDef
        ;
    var canvas;
    var gravity = new b2Vec2(0,20);
    var world = new b2World(gravity,true);
    var context;
    var img_path="/wp-content/themes/a-good-catch/images/";
    /*
    var the_pivot=new b2CircleDef;
    var bd;
    var the_box
     // pivot for revolute joint
    the_pivot.radius=0.2;
    the_pivot.density=0;
    bd=new b2BodyDef  ;
    bd.position.Set(3,6.5);
    var rev_joint=world.CreateBody(bd);
    rev_joint.CreateShape(the_pivot);
    rev_joint.SetMassFromShapes();
    // box for the revolute joint
    the_box.SetAsBox(2,0.1);
    the_box.density=0.01;
    the_box.friction=1;
    the_box.restitution=0.1;
    bd=new b2BodyDef  ;
    bd.position.Set(3,6.5);
    var rev_box=world.CreateBody(bd);
    rev_box.CreateShape(the_box);
    rev_box.SetMassFromShapes();
    // revolute joint
    the_rev_joint.Initialize(rev_joint,rev_box,new b2Vec2(3,6.5));
    the_rev_joint.enableMotor=true;
    the_rev_joint.motorSpeed=10;
    the_rev_joint.maxMotorTorque=1000;
    var joint_added=world.CreateJoint(the_rev_joint);
*/
         
    var fixDef = new b2FixtureDef;
    fixDef.density = 1.0;
    fixDef.friction = 0.1;
    fixDef.restitution = 0.2;
     
    var bodyDef = new b2BodyDef;
         
    //create ground
    bodyDef.type = b2Body.b2_staticBody;
    fixDef.shape = new b2PolygonShape;
    
    fixDef.shape.SetAsBox(100, 0);
    //上下两个挡板
    bodyDef.position.Set(10, 0);
    world.CreateBody(bodyDef).CreateFixture(fixDef);    
    bodyDef.position.Set(10, 45);
    world.CreateBody(bodyDef).CreateFixture(fixDef);
    
    fixDef.shape.SetAsBox(0, 50);
    //左右两个挡板
    bodyDef.position.Set(0, 13);
    world.CreateBody(bodyDef).CreateFixture(fixDef);    
    bodyDef.position.Set(100, 13);
    world.CreateBody(bodyDef).CreateFixture(fixDef);
 
     //create some objects
     bodyDef.type = b2Body.b2_dynamicBody;
     
     
     fixDef.shape = new b2CircleShape(1);
     bodyDef.position.x = 5;
     bodyDef.position.y = 6;
     var data = new Object();
     data.imgSrc="catstand.gif";
     data.width=16;
     data.height=20;
     
     bodyDef.userData = data;
     var objTopWheel = world.CreateBody(bodyDef);
     objTopWheel.CreateFixture(fixDef);
     
     
     fixDef.shape = new b2PolygonShape;
     fixDef.shape.SetAsBox(1,1);
     bodyDef.position.x = 8;
     bodyDef.position.y = 6;
     var data = new Object();
     data.imgSrc="redbull.gif";
     data.width=20;
     data.height=20;
     
     bodyDef.userData = data;
     var part2 = world.CreateBody(bodyDef);
     part2.CreateFixture(fixDef);
     
     

     /*
     //距离关节测试 
     var jointDef = new b2DistanceJointDef;
     jointDef.Initialize(objTopWheel, part2, new b2Vec2(5,6),new b2Vec2(8,6));
     jointDef.collideConnected = true;
     world.CreateJoint(jointDef);
     */
    
    
    /*
     * 旋转关节测试
     */
    
     /*
     */
     var rvlt = new b2RevoluteJointDef;
     rvlt.Initialize(objTopWheel,part2,new b2Vec2(5,16));
     world.CreateJoint(rvlt);
       
       
      /*
       * 移动关节测试
       */
      
    /*
    var jointDef = new b2PrismaticJointDef;
    var worldAxis = new b2Vec2(1.0, 0.0);
    jointDef.Initialize(objTopWheel, part2,new b2Vec2(5,6),worldAxis);
    
    jointDef.lowerTranslation = -5.0;
    jointDef.upperTranslation = 2.5;
    jointDef.enableLimit = true;
    jointDef.motorForce = 1.0;
    jointDef.motorSpeed = 0.0;
    jointDef.enableMotor = true;
    world.CreateJoint(jointDef);
    */
    
    
    /*
     * 滑轮关节测试
     */
    
    /*
    var anchor1 = objTopWheel.GetWorldCenter();
    var anchor2 = part2.GetWorldCenter();
    var groundAnchor1 = new b2Vec2(anchor1.x, anchor1.y -2.0);
    var groundAnchor2 = new b2Vec2(anchor2.x, anchor2.y -5.0);
    var ratio = 1.0;
    var jointDef = new b2PulleyJointDef;
    jointDef.Initialize(objTopWheel, part2, groundAnchor1, groundAnchor2, anchor1, anchor2, ratio);
    jointDef.maxLength1 = 9.0;
    jointDef.maxLength2 = 8.0;
    world.CreateJoint(jointDef);
    */
   
   
   /*
    * 
    * 齿轮关节测试(not finished)
    */
   
   /*
    var jointDef = new b2GearJointDef;
    jointDef.body1 = objTopWheel;
    jointDef.body2 = part2;
    jointDef.joint1 = myRevoluteJoint;
    jointDef.joint2 = myPrismaticJoint;
    jointDef.ratio = 2.0f * b2_pi / myLength;
    */
    

         /*
            
         for(var i = 0; i < 10; ++i) {
            if(Math.random() > 0) {
               fixDef.shape = new b2PolygonShape;
               fixDef.shape.SetAsBox(
                     Math.random() + 0.1 //half width
                  ,  Math.random() + 0.1 //half height
               );
            } else {
               fixDef.shape = new b2CircleShape(
                  Math.random() + 0.1 //radius
               );
            }
            bodyDef.position.x = Math.random() * 10;
            bodyDef.position.y = Math.random() * 10;
            world.CreateBody(bodyDef).CreateFixture(fixDef);

         }
         */
        
        
         /*
         //  making a car
    //  two wheels
              bodyDef = new b2BodyDef;
              bodyDef.type = b2Body.b2_dynamicBody;
             fixDef = new b2FixtureDef;
           fixDef.density = 30;
           fixDef.friction = 10;
           fixDef.restitution = 0.1;
           fixDef.shape = new b2CircleShape(0.3)
    //  wheel1
     
             var wheel1=world.CreateBody(bodyDef)
                 wheel1.CreateFixture(fixDef);
    //  wheel2
             var wheel2=world.CreateBody(bodyDef)
                 wheel2.CreateFixture(fixDef);
     
    //  convex car body
             var bodyDef = new b2BodyDef;
                 bodyDef.type = b2Body.b2_dynamicBody;
                 bodyDef.position.Set(24,9)
    //  just change the fixDef.shape and keep other properties
                 fixDef.shape = new b2PolygonShape
                 fixDef.shape.SetAsArray([
                    new b2Vec2(1 , -1.2),
                        new b2Vec2(1.5, -0.5),
                        new b2Vec2(1.3 , 0),
                        new b2Vec2(-1.3, 0),
                        new b2Vec2(-1.5, -0.5),
                        new b2Vec2(-0.3 , -1.2)
                        ]);
     
              var car = world.CreateBody(bodyDef);
                  car.CreateFixture(fixDef);
     
    //  joints
              var myjoint = new b2RevoluteJointDef();
                  myjoint.bodyA = car;
                  myjoint.bodyB = wheel1;
                  myjoint.localAnchorA.Set(-0.7,0);
                  myjoint.enableMotor = true;
                  myjoint.maxMotorTorque = 55;
                  myjoint.motorSpeed=-10;
              world.CreateJoint(myjoint);
     
                  myjoint.bodyA = car;
                  myjoint.bodyB = wheel2;
                  myjoint.localAnchorA.Set(0.8,0);
              world.CreateJoint(myjoint);

*/


         //setup debug draw
         var scale = 10;
         var debugDraw = new b2DebugDraw();
         canvas = document.getElementById( 'canvas' );
         context = canvas.getContext("2d");
         debugDraw.SetSprite(context);
         debugDraw.SetDrawScale(scale);
         debugDraw.SetFillAlpha(0.8);
         debugDraw.SetLineThickness(0.5);
         debugDraw.SetFlags(b2DebugDraw.e_shapeBit | b2DebugDraw.e_jointBit);
         world.SetDebugDraw(debugDraw);
         
         window.setInterval(update, 1000 / 60);
         //mouse
         
         var mouseX, mouseY, mousePVec, isMouseDown, selectedBody, mouseJoint;
         var canvasPosition = getElementPosition(document.getElementById("canvas"));
         
         document.addEventListener("mousedown", function(e) {
            isMouseDown = true;
            handleMouseMove(e);
            document.addEventListener("mousemove", handleMouseMove, true);
         }, true);
         
         document.addEventListener("mouseup", function() {
            document.removeEventListener("mousemove", handleMouseMove, true);
            isMouseDown = false;
            mouseX = undefined;
            mouseY = undefined;
         }, true);
         
         function handleMouseMove(e) {
            mouseX = (e.clientX - canvasPosition.x) / scale;
            mouseY = (e.clientY - canvasPosition.y) / scale;
         };
         
         function getBodyAtMouse() {
            mousePVec = new b2Vec2(mouseX, mouseY);
            var aabb = new b2AABB();
            aabb.lowerBound.Set(mouseX - 0.001, mouseY - 0.001);
            aabb.upperBound.Set(mouseX + 0.001, mouseY + 0.001);
            
            // Query the world for overlapping shapes.

            selectedBody = null;
            world.QueryAABB(getBodyCB, aabb);
            return selectedBody;
         }

         function getBodyCB(fixture) {
            if(fixture.GetBody().GetType() != b2Body.b2_staticBody) {
               if(fixture.GetShape().TestPoint(fixture.GetBody().GetTransform(), mousePVec)) {
                  selectedBody = fixture.GetBody();
                  return false;
               }
            }
            return true;
         }
         
         //update
         
         function update() {
         
            if(isMouseDown && (!mouseJoint)) {
               var body = getBodyAtMouse();
               if(body) {
                  var md = new b2MouseJointDef();
                  md.bodyA = world.GetGroundBody();
                  md.bodyB = body;
                  md.target.Set(mouseX, mouseY);
                  md.collideConnected = true;
                  md.maxForce = 300.0 * body.GetMass();
                  mouseJoint = world.CreateJoint(md);
                  body.SetAwake(true);
               }
            }
            
            if(mouseJoint) {
               if(isMouseDown) {
                  mouseJoint.SetTarget(new b2Vec2(mouseX, mouseY));
               } else {
                  world.DestroyJoint(mouseJoint);
                  mouseJoint = null;
               }
            }
         
            world.Step(1 / 60, 10, 10);
            world.DrawDebugData();
            world.ClearForces();
            drawAvator();
         };
         
         //helpers
         
         //http://js-tut.aardon.de/js-tut/tutorial/position.html
         function getElementPosition(element) {
            var elem=element, tagname="", x=0, y=0;
           
            while((typeof(elem) == "object") && (typeof(elem.tagName) != "undefined")) {
               y += elem.offsetTop;
               x += elem.offsetLeft;
               tagname = elem.tagName.toUpperCase();

               if(tagname == "BODY")
                  elem=0;

               if(typeof(elem) == "object") {
                  if(typeof(elem.offsetParent) == "object")
                     elem = elem.offsetParent;
               }
            }

            return {x: x, y: y};
         }


        function drawPreloading()
        {
            // var cxt=context;
            // var img_src="/wp-content/themes/a-good-catch/images/home.gif";
            // preImage(img_src,function(){  
                // cxt.drawImage(this,150,50);
            // }); 
            
            
            // var img = new Image();
            // img.onload = function()
            // {
                // cxt.drawImage(img,0,0);
            // }
            // img.src="/wp-content/themes/a-good-catch/images/home.gif";
            
         // var imgtest = document.getElementById( 'imagetest' );
         // var imgc = new Image();
         // var img_src="/wp-content/themes/a-good-catch/images/home.gif";
         // imgc.src = img_src;
         // imgtest.drawImage(imgc,20,20);
         // alert(imgtest);
         // imgtest.font = "bold 60px arial";
         // imgtest.innerText = 'aaaaa';
            // cxt.font = "bold 60px arial";
            // cxt.textAlign = "left";
            // var myTime = new Date();
            // var snd = myTime.getSeconds();
            // cxt.fillStyle = "#00ff00";
            // cxt.fillText( "- LOADING -", 200 + 20 * Math.sin(snd) , 150);
            // ctx.fillRect(300,150,430,0);
            // var imgc = new Image();
            // var img_src="http://blog-dev/wp-content/themes/a-good-catch/images/home.gif";
            // preImage(img_src,function(){  
                // imgtest.drawImage(this,20,20);  
                // alert('in callback');
            // }); 
//             
        }   
        
        function drawAvator()
        {
            var cxt=context;
            var img_file;
            var userData;
            for (var b = world.GetBodyList(); b; b = b.GetNext())
            {
                userData = b.GetUserData();
                if(userData)
                {
                    //try to draw user's image
                    img_file = userData.imgSrc;
                    // alert(img_path + img_file);
                    preImage(img_path + img_file,function()
                    {  
                        cxt.save();
                        cxt.rotate(b.GetAngle()/scale);
                        cxt.scale(0.5,1);
                        cxt.drawImage(this,b.GetPosition().x*scale,b.GetPosition().y*scale);
                        cxt.restore();
                    }); 
                }
            }
        }
        
        function preImage(url,callback){  
             var img = new Image(); //创建一个Image对象，实现图片的预下载  
             img.src = url;  
             
            if (img.complete) { // 如果图片已经存在于浏览器缓存，直接调用回调函数  
                 callback.call(img);  
                return; // 直接返回，不用再处理onload事件  
             }  
             img.onload = function () { //图片下载完毕时异步调用callback函数。  
                 callback.call(img);//将回调函数的this替换为Image对象  
             };  
        }  

      };